home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 4 / Amiga Tools 4.iso / tools / netzwerk / parnet-filesystem / pack.c < prev    next >
C/C++ Source or Header  |  1996-02-26  |  22KB  |  839 lines

  1. /*-
  2.  * $Id: pack.c,v 1.3 1995/11/14 00:43:34 Rhialto Exp $
  3.  * $Log: pack.c,v $
  4.  * Revision 1.3  1995/11/14  00:43:34  Rhialto
  5.  * More casts for yet stricter DICE type checking...
  6.  *
  7.  * Revision 1.2  1995/11/14  00:08:15  Rhialto
  8.  * #ifdef -> #if; fix workaround for AttemptLockDosList();
  9.  * cater to stricter compiler.
  10.  *
  11.  * Revision 1.1  1993/12/02  20:45:46  Rhialto
  12.  * Initial revision
  13.  *
  14.  *
  15.  *  Originally:
  16.  *
  17.  *    DOSDEVICE.C        V1.10   2 November 1987
  18.  *
  19.  *    EXAMPLE DOS DEVICE DRIVER FOR AZTEC.C    PUBLIC DOMAIN.
  20.  *
  21.  *    By Matthew Dillon.
  22.  *
  23.  *  This has been stripped and refilled with network filesystem code
  24.  *  by Olaf Seibert.
  25.  *
  26.  *  This code is (C) Copyright 1993,1995 by Olaf Seibert. All rights reserved.
  27.  *  May not be used or copied without a licence.
  28. -*/
  29.  
  30. #include "netfs.h"
  31. #include <string.h>
  32.  
  33. #if DEBUG
  34. #   include "syslog.h"
  35. #else
  36. #   define    debug(x)
  37. #endif
  38.  
  39.  
  40. #define NETFL(something)     ((NetFileLock *)(something))
  41. #define NETFH(something)     ((NetFileHandle *)(something))
  42.  
  43. Prototype struct ExecBase *SysBase;
  44. Prototype struct MsgPort *DosPort;
  45. Prototype struct DeviceNode *DevNode;
  46. Prototype struct DeviceList *VolNode;
  47. Prototype long        UnitNr;
  48. Prototype char       *DevName;
  49. Prototype ULONG     DevFlags;
  50. Prototype struct DosPacket *DosPacket;
  51. Prototype ULONG     error;
  52.  
  53. Local BPTR MakeFileLock(NetFileLock *netfl, struct FileLock *fl, long mode);
  54.  
  55. /*
  56.  * Since this code might be called several times in a row without being
  57.  * unloaded, you CANNOT ASSUME GLOBALS HAVE BEEN ZERO'D!!  This also goes
  58.  * for any global/static assignments that might be changed by running the
  59.  * code.
  60.  */
  61.  
  62. struct MsgPort    *DosPort;    /* Our DOS port... */
  63. struct DeviceNode *DevNode;    /* Our DOS node.. created by DOS for us */
  64. struct DeviceList *VolNode;    /* Device List structure for our volume
  65.                  * node */
  66. /*
  67.  * dc1 3.13 (10.1.95) Commercial gives a spurious warning on the next line.
  68.  */
  69. struct DosLibrary *DOSBase;    /* DOS library base */
  70. long        WaitMask;    /* The signal mask to wait for */
  71. long        UnitNr;     /* From */
  72. char           *DevName;    /*   the */
  73. ULONG        DevFlags;    /*     mountlist */
  74. struct DosPacket *DosPacket;    /* For the SystemRequest pr_WindowPtr */
  75. long        OpenCount;    /* How many open files/locks there are */
  76. ULONG        error;
  77.  
  78.  
  79. /*
  80.  * Don't call the entry point main().  This way, if you make a mistake
  81.  * with the compile options you'll get a link error.
  82.  */
  83.  
  84. Prototype void netfilesyshandler(void);
  85.  
  86. void
  87. handlermain(void)
  88. {
  89.     register struct DosPacket *packet;
  90.     struct Message *msg;
  91.     short        done;
  92.  
  93.     /*
  94.      * Initialize all global variables.  SysBase MUST be initialized
  95.      * before we can make Exec calls.  AbsExecBase is a library symbol
  96.      * referencing absolute memory location 4.
  97.      */
  98.  
  99.     DOSBase = OpenLibrary("dos.library", 0L);
  100.  
  101. #if DEBUG
  102.     /*
  103.      * Initialize debugging code as soon as possible. Only SysBase required.
  104.      */
  105.  
  106.     initsyslog();
  107. #endif                /* DEBUG */
  108.  
  109.     DosPort = &((struct Process *)FindTask(NULL))->pr_MsgPort;
  110.  
  111.     debug(("WaitPort DosPort for startup...\n"));
  112.     WaitPort(DosPort);      /* Get Startup Packet  */
  113.     debug(("WaitPort DosPort done\n"));
  114.     msg = GetMsg(DosPort);
  115.     packet = (struct DosPacket *) msg->mn_Node.ln_Name;
  116.  
  117.     DevNode = BTOC(PArg3);
  118.     {
  119.     struct FileSysStartupMsg *fssm;
  120.     struct DosEnvec *de;
  121.  
  122.     DevName = "parnet.device";
  123.     UnitNr = 0;
  124.     DevFlags = 0;
  125.  
  126.     if (fssm = (struct FileSysStartupMsg *)BTOC(DevNode->dn_Startup)) {
  127.                     /* Same as BTOC(packet->dp_Arg2) */
  128.         UnitNr = fssm->fssm_Unit;
  129.         if (fssm->fssm_Device)
  130.         DevName = (char *)BTOC(fssm->fssm_Device)+1;
  131.         DevFlags = fssm->fssm_Flags;
  132.         de = BTOC(fssm->fssm_Environ);
  133.  
  134.         ClientDefaults(de->de_BlocksPerTrack, de->de_Interleave);
  135.     }
  136.     }
  137.  
  138.     if (DOSBase && OpenNetFS() == 0) {
  139.     /*
  140.      * Loading DevNode->dn_Task causes DOS *NOT* to startup a new
  141.      * instance of the device driver for every reference.    E.G. if
  142.      * you were writing a CON: device you would want this field to be
  143.      * NULL.
  144.      */
  145.  
  146.     DevNode->dn_Task = DosPort;
  147.  
  148.     PRes1 = DOSTRUE;
  149.     PRes2 = 0;
  150.     } else {            /* couldn't open dos.library  */
  151.     PRes1 = DOSFALSE;
  152.     PRes2 = ERROR_DEVICE_NOT_MOUNTED;   /* no better message available */
  153.     returnpacket(packet);
  154.     goto exit;        /* exit process    */
  155.     }
  156.     returnpacket(packet);
  157.  
  158.     /*
  159.      * Get the first real packet.
  160.      * This seems to be necessary because adding our Volume node at
  161.      * this point causes some kind of deadlock. Which is kind
  162.      * of silly since we returned the startup packet. Even calling
  163.      * AttemptLockDosList does not seem to give any indication...
  164.      */
  165.     debug(("WaitPort DosPort for 1st real packet...\n"));
  166.     WaitPort(DosPort);
  167.     debug(("WaitPort DosPort done\n"));
  168.     msg = GetMsg(DosPort);
  169.  
  170.     {
  171.     struct DateStamp ds;
  172.  
  173.     DateStamp(&ds);
  174.     VolNode = NewVolNode("Network", &ds);
  175.     debug(("VolNode done\n"));
  176.     }
  177.     /* Initialize some more global variables    */
  178.  
  179.     OpenCount = 0;
  180.     WaitMask = (1L << DosPort->mp_SigBit) |
  181.            (1L << RdPort->mp_SigBit);
  182.  
  183.     done = -1;
  184.  
  185.     goto entry;
  186.  
  187.     /*
  188.      * Here begins the endless loop, waiting for requests over our message
  189.      * port and executing them.  Since requests are sent over the message
  190.      * port in our device and volume nodes, we must not use our Process
  191.      * message port for this: this precludes being able to call DOS
  192.      * functions ourselves.
  193.      */
  194.  
  195. top:
  196.     for (done = -1; done < 0;) {
  197.     Wait(WaitMask);
  198.     wakeup:
  199.     while (msg = GetMsg(RdPort)) {
  200.         /* Handle unsollicited network input */
  201.         DoProtocol(msg, ((struct IOStdReq *)msg)->io_Data);
  202.     }
  203.     while (msg = GetMsg(DosPort)) {
  204.     entry:
  205.  
  206.         packet = (PACKET *) msg->mn_Node.ln_Name;
  207.         PRes1 = DOSFALSE;
  208.         PRes2 = 0;
  209.         error = 0;
  210.         debug(("Packet: %4ld %08lx %08lx %08lx %s\n",
  211.              PType, PArg1, PArg2, PArg3, typetostr(PType)));
  212.  
  213.         DosPacket = packet;     /* For the System Requesters */
  214.         ReqPacket.p_Action = PType;
  215.  
  216.         switch (PType) {
  217.         case ACTION_DIE:        /* attempt to die?  */
  218.         done = (PArg1 == MSH_MAGIC) ? PArg2 : 0;   /* Argh! Hack! */
  219.         break;
  220.         case ACTION_CURRENT_VOLUME: /* -               VolNode,UnitNr*/
  221.         PRes1 = (long) CTOB(VolNode);
  222.         PRes2 = UnitNr;
  223.         break;
  224.         case ACTION_LOCATE_OBJECT:    /* Lock,Name,Mode    Lock         */
  225.         {
  226.             struct FileLock *lock;
  227.             NetFileLock     *netfl;
  228.             long        lockmode;
  229.  
  230.             lock = BTOC(PArg1);
  231.             if ((lockmode = PArg3) != EXCLUSIVE_LOCK)
  232.             lockmode = SHARED_LOCK;
  233.             netfl = NetLock(NETFL(lock ? lock->fl_Key : 0),
  234.                   BTOC(PArg2),
  235.                   lockmode);
  236.             PRes1 = MakeFileLock(netfl, lock, lockmode);
  237.         }
  238.         break;
  239.         case ACTION_RENAME_DISK:    /* BSTR:NewName        Bool      */
  240.         NewVolNodeName(BTOC(PArg1));
  241.         PRes1 = DOSTRUE;
  242.         break;
  243.         case ACTION_FREE_LOCK:    /* Lock            Bool      */
  244.         {
  245.             struct FileLock *lock;
  246.             NetFileLock    *netfl;
  247.  
  248.             PRes1 = DOSTRUE;
  249.             lock = BTOC(PArg1);
  250.             if (lock == NULL)
  251.             break;
  252.  
  253.             netfl = NETFL(lock->fl_Key);
  254.             FreeFileLock(lock);
  255.             NetUnLock(netfl);
  256.         }
  257.         break;
  258.         case ACTION_DELETE_OBJECT:    /* Lock,Name        Bool         */
  259.         {
  260.             struct FileLock *lock;
  261.  
  262.             lock = BTOC(PArg1);
  263.             PRes1 = NetDeleteFile(NETFL(lock ? lock->fl_Key : 0),
  264.                      BTOC(PArg2));
  265.         }
  266.         break;
  267.         case ACTION_RENAME_OBJECT:    /* SLock,SName,DLock,DName   Bool    */
  268.         {
  269.             struct FileLock *slock, *dlock;
  270.  
  271.             slock = BTOC(PArg1);
  272.             dlock = BTOC(PArg3);
  273.             PRes1 = NetRename(NETFL(slock ? slock->fl_Key : 0),
  274.                      BTOC(PArg2),
  275.                      NETFL(dlock ? dlock->fl_Key : 0),
  276.                      BTOC(PArg4));
  277.         }
  278.         break;
  279.         case ACTION_MORECACHE:    /* #BufsToAdd        bool,numbufs */
  280.         PRes1 = 0;        /* observed behaviour in std filesystem */
  281.         PRes2 = 0;        /* documented behaviour in manual */
  282.         break;
  283.         case ACTION_COPY_DIR:    /* Lock            Lock      */
  284.         {
  285.             struct FileLock *lock;
  286.             NetFileLock *netfl;
  287.  
  288.             lock = BTOC(PArg1);
  289.  
  290.             netfl = NetDupLock(NETFL(lock ? lock->fl_Key : 0));
  291.  
  292.             PRes1 = MakeFileLock(netfl, lock,
  293.                      lock ? lock->fl_Access : SHARED_LOCK);
  294.         }
  295.         break;
  296.         case ACTION_SET_PROTECT:    /* -,Lock,Name,Mask       Bool      */
  297.         {
  298.             struct FileLock *lock;
  299.  
  300.             lock = BTOC(PArg2);
  301.             PRes1 = NetSetProtect(NETFL(lock ? lock->fl_Key : 0),
  302.                     BTOC(PArg3), PArg4);
  303.         }
  304.         break;
  305.         case ACTION_CREATE_DIR:    /* Lock,Name        Lock         */
  306.         {
  307.             struct FileLock *lock;
  308.             NetFileLock *netfl;
  309.  
  310.             lock = BTOC(PArg1);
  311.  
  312.             netfl = NetCreateDir(NETFL(lock ? lock->fl_Key : 0),
  313.                        BTOC(PArg2));
  314.  
  315.             PRes1 = MakeFileLock(netfl, lock, SHARED_LOCK);
  316.         }
  317.         break;
  318.         case ACTION_EXAMINE_OBJECT: /* Lock,Fib           Bool         */
  319.         {
  320.             struct FileLock *lock;
  321.  
  322.             lock = BTOC(PArg1);
  323.             PRes1 = NetExamine(NETFL(lock ? lock->fl_Key : 0),
  324.                       BTOC(PArg2));
  325.         }
  326.         break;
  327.         case ACTION_EXAMINE_NEXT:    /* Lock,Fib           Bool         */
  328.         {
  329.             struct FileLock *lock;
  330.  
  331.             lock = BTOC(PArg1);
  332.             PRes1 = NetExNext(NETFL(lock ? lock->fl_Key : 0),
  333.                      BTOC(PArg2));
  334.         }
  335.         break;
  336.         case ACTION_DISK_INFO:    /* InfoData           Bool:TRUE     */
  337.         PRes1 = NetDiskInfo(BTOC(PArg1));
  338.         break;
  339.         case ACTION_INFO:    /* Lock,InfoData           Bool:TRUE     */
  340.         {
  341.             struct FileLock *lock;
  342.  
  343.             lock = BTOC(PArg1);
  344.             PRes1 = NetInfo(NETFL(lock ? lock->fl_Key : 0),
  345.                      BTOC(PArg2));
  346.         }
  347.         break;
  348. /*        case ACTION_FLUSH:        / * writeout bufs, disk motor off     */
  349.         case ACTION_SET_COMMENT:    /* -,Lock,Name,Comment       Bool      */
  350.         {
  351.             struct FileLock *lock;
  352.  
  353.             lock = BTOC(PArg2);
  354.             PRes1 = NetSetComment(NETFL(lock ? lock->fl_Key : 0),
  355.                       BTOC(PArg3), BTOC(PArg4));
  356.         }
  357.         break;
  358.         case ACTION_PARENT: /* Lock                ParentLock    */
  359.         {
  360.             struct FileLock *lock;
  361.             NetFileLock *netfl;
  362.  
  363.             lock = BTOC(PArg1);
  364.  
  365.             netfl = NetParentDir(NETFL(lock ? lock->fl_Key : 0));
  366.  
  367.             PRes1 = MakeFileLock(netfl, lock, SHARED_LOCK);
  368.         }
  369.         break;
  370.         case ACTION_INHIBIT:    /* Bool            Bool      */
  371.         PRes1 = DOSFALSE;
  372.         break;
  373.         case ACTION_SET_DATE: /* -,Lock,Name,CPTRDateStamp       Bool      */
  374.         {
  375.             struct FileLock *lock;
  376.  
  377.             lock = BTOC(PArg2);
  378.             PRes1 = NetSetDate(NETFL(lock ? lock->fl_Key : 0),
  379.                       BTOC(PArg3),
  380.                       (struct DateStamp *)PArg4);
  381.         }
  382.         break;
  383.         case ACTION_SAME_LOCK:  /* Lock1,Lock2           Result    */
  384.         {
  385.             struct FileLock *fl1, *fl2;
  386.  
  387.             fl1 = BTOC(PArg1);
  388.             fl2 = BTOC(PArg2);
  389.             if (fl1->fl_Volume == fl2->fl_Volume &&
  390.             BTOC(fl1->fl_Volume) == VolNode) {
  391.             PRes1 = NetSameLock(NETFL(fl1->fl_Key),
  392.                        NETFL(fl2->fl_Key));
  393.             } else {
  394.             PRes1 = DOSFALSE;
  395.             error = ERROR_INVALID_LOCK;
  396.             }
  397.         }
  398.         break;
  399.         case ACTION_READ:    /* FHArg1,CPTRBuffer,Length      ActLength  */
  400.         PRes1 = NetRead(NETFH(PArg1), (UBYTE *)PArg2, PArg3);
  401.         break;
  402.         case ACTION_WRITE:    /* FHArg1,CPTRBuffer,Length      ActLength  */
  403.         PRes1 = NetWrite(NETFH(PArg1), (UBYTE *)PArg2, PArg3);
  404.         break;
  405.         case ACTION_OPENRW:     /* FileHandle,Lock,Name    Bool      */
  406.         case ACTION_OPENOLD:    /* FileHandle,Lock,Name    Bool      */
  407.         case ACTION_OPENNEW:    /* FileHandle,Lock,Name    Bool      */
  408.         {
  409.             NetFileHandle *netfh;
  410.             struct FileHandle *fh;
  411.             struct FileLock *lock;
  412.  
  413.             fh = BTOC(PArg1);
  414.             lock = BTOC(PArg2);
  415.             netfh = NetOpen(NETFL(lock ? lock->fl_Key : 0),
  416.                   BTOC(PArg3),
  417.                   PType);
  418.             if (netfh) {
  419.             fh->fh_Arg1 = (long) netfh;
  420.             PRes1 = DOSTRUE;
  421.             OpenCount++;
  422.             }
  423.         }
  424.         break;
  425.         case ACTION_CLOSE:    /* FHArg1            Bool:Success */
  426.         PRes1 = NetClose(NETFH(PArg1));
  427.         OpenCount--;
  428.         break;
  429.         case ACTION_SEEK:    /* FHArg1,Position,Mode      OldPosition */
  430.         PRes1 = NetSeek(NETFH(PArg1), PArg2, PArg3);
  431.         break;
  432. #ifdef notdef
  433.         case ACTION_FORMAT: /* vol,type            Bool:success */
  434.         PRes1 = NetFormat(BTOC(PArg1), PArg2);
  435.         break;
  436. #endif
  437.         case ACTION_MAKE_LINK: /* parent,name,target,soft       Bool      */
  438.         {
  439.             struct FileLock *lock;
  440.             void        *dest;
  441.  
  442.             lock = BTOC(PArg1);
  443.             dest = PArg4 ? (char *)PArg3            /* C string! */
  444.                  : (void *)((struct FileLock *)BTOC(PArg3))->fl_Key;
  445.             PRes1 = NetMakeLink(NETFL(lock ? lock->fl_Key : 0),
  446.                     BTOC(PArg2),
  447.                     dest,
  448.                     PArg4);
  449.         }
  450.         break;
  451.         case ACTION_READ_LINK: /* parent,name,target,size       length    */
  452.         {
  453.             struct FileLock *lock;
  454.             lock = BTOC(PArg1);
  455.             PRes1 = NetReadLink(NETFL(lock ? lock->fl_Key : 0),
  456.                     (char *)PArg2,      /* C string! */
  457.                     (char *)PArg3,
  458.                     PArg4);
  459.         }
  460.         break;
  461.         case ACTION_SET_FILE_SIZE:
  462.         PRes1 = NetSetFileSize(NETFH(PArg1), PArg2, PArg3);
  463.         break;
  464. /*        case ACTION_WRITE_PROTECT: */
  465.                 /* FH,Lock                BOOL     */
  466.         case ACTION_FH_FROM_LOCK:
  467.         {
  468.             NetFileHandle *netfh;
  469.             struct FileHandle *fh;
  470.             struct FileLock *lock;
  471.  
  472.             fh = BTOC(PArg1);
  473.             lock = BTOC(PArg2);
  474.             netfh = NetOpenFromLock(NETFL(lock ? lock->fl_Key : 0));
  475.             if (netfh) {
  476.             fh->fh_Arg1 = (long) netfh;
  477.             PRes1 = DOSTRUE;
  478.             OpenCount++;
  479.             /* Discard the lock */
  480.             FreeFileLock(lock);
  481.             }
  482.         }
  483.         break;
  484.         case ACTION_IS_FILESYSTEM:
  485.         PRes1 = DOSTRUE;
  486.         break;
  487.         case ACTION_CHANGE_MODE:
  488.         {
  489.             void *object;
  490.  
  491.             switch (PArg1) {
  492.             case CHANGE_FH:
  493.             object = NETFH(((struct FileHandle *)BTOC(PArg2))->fh_Arg1);
  494.             break;
  495.             case CHANGE_LOCK:
  496.             object = NETFL(((struct FileLock *)BTOC(PArg2))->fl_Key);
  497.             break;
  498.             }
  499.             PRes1 = NetChangeMode(PArg1, object, PArg3);
  500.         }
  501.         break;
  502.         case ACTION_COPY_DIR_FH:    /* fh_Arg1           Lock      */
  503.         case ACTION_PARENT_FH:
  504.         {
  505.             NetFileLock *netfl;
  506.  
  507.             if (PType == ACTION_PARENT_FH)
  508.             netfl = NetParentOfFH(NETFH(PArg1));
  509.             else
  510.             netfl = NetDupLockFromFH(NETFH(PArg1));
  511.  
  512.             /* User has inserted disk by now, so we can use VolNode */
  513.             PRes1 = MakeFileLock(netfl, NULL, SHARED_LOCK);
  514.         }
  515.         break;
  516.         case ACTION_EXAMINE_FH:     /* fh_Arg1,Fib         Bool      */
  517.         PRes1 = NetExamineFH(NETFH(PArg1), BTOC(PArg2));
  518.         break;
  519.         /*
  520.          * A few other packet types which we do not support
  521.          */
  522.         case ACTION_LOCK_RECORD:    /* fh,pos,len,mode,time    Bool      */
  523.         {
  524.             debug(("fh(arg1) %x\n", PArg1));
  525.  
  526.             NetLockRecord(packet, NETFH(PArg1), PArg2, PArg3, PArg4, PArg5);
  527.             packet = NULL;
  528.         }
  529.         break;
  530.         case ACTION_FREE_RECORD:    /* fh,pos,len           Bool      */
  531.         {
  532.             debug(("fh(arg1) %x\n", PArg1));
  533. /*            NetFileHandle *netfh = NETFH(((struct FileHandle *)
  534.                           PArg1)->fh_Arg1); */
  535.  
  536.             PRes1 = NetFreeRecord(NETFH(PArg1), PArg2, PArg3);
  537.         }
  538.         break;
  539. /*        case ACTION_WAIT_CHAR:     / * Timeout, ticks       Bool      */
  540. /*        case ACTION_RAWMODE:       / * Bool(-1:RAW 0:CON)      OldState  */
  541.         default:
  542.         PRes1 = DOSFALSE;
  543.         error = ERROR_ACTION_NOT_KNOWN;
  544.         break;
  545.         } /* end switch */
  546.         if (packet) {
  547.         if (error)
  548.             PRes2 = error;
  549.         debug(("RES=%06lx, ERR=%ld\n", PRes1, error));
  550.         returnpacket(packet);
  551.         DosPacket = NULL;
  552.         }
  553. #if DEBUG
  554.         else {
  555.         debug(("NOREP\n"));
  556.         }
  557. #endif
  558.     } /* end while (GetMsg()) */
  559.  
  560.     } /* end for (;done) */
  561.  
  562. #if DEBUG
  563.     debug(("Can we remove ourselves? "));
  564. #endif                /* DEBUG */
  565.     Forbid();
  566.     if (OpenCount || packetsqueued()) {
  567.     Permit();
  568.     debug((" ..  not yet!\n"));
  569.     goto top;        /* sorry... can't exit     */
  570.     }
  571.     debug((" .. yes!\n"));
  572.  
  573.     /*
  574.      * Causes a new process to be created on next reference.
  575.      */
  576.  
  577.     DevNode->dn_Task = NULL;
  578.     CloseNetFS();
  579.     FreeVolNode(VolNode);
  580.     debug(("CloseNetFS() returned.\n"));
  581.  
  582.     /*
  583.      * Remove debug, closedown, fall of the end of the world.
  584.      */
  585. exit:
  586. #if DEBUG
  587.     uninitsyslog();
  588. #endif                /* DEBUG */
  589.  
  590.     if (done & 2)
  591.     UnLoadSeg(DevNode->dn_SegList); /* This is real fun. We are still */
  592.     if (done & (2 | 1))
  593.     DevNode->dn_SegList = 0;    /* Forbid()den, fortunately */
  594.  
  595.     CloseLibrary((struct Library *)DOSBase);
  596.  
  597.     /* Fall off the end of the world. Implicit Permit(). */
  598. }
  599.  
  600. /*
  601.  *  Make a new struct FileLock, for DOS use. It is put on a singly linked
  602.  *  list, which is attached to the same VolumeNode the old lock was on.
  603.  *
  604.  *  Also note that we must ALWAYS be prepared to UnLock() or DupLock()
  605.  *  any FileLocks we ever made, even if the volume in question has been
  606.  *  removed and/or inserted into another drive with another FileSystem
  607.  *  handler!
  608.  *
  609.  * DOS makes certain assumptions about LOCKS.    A lock must minimally be a
  610.  * FileLock structure, with additional private information after the
  611.  * FileLock structure.    The longword before the beginning of the structure
  612.  * must contain the length of structure + 4.
  613.  *
  614.  * NOTE!!!!! The workbench does not follow the rules and assumes it can copy
  615.  * lock structures.  This means that if you want to be workbench
  616.  * compatible, your lock structures must be EXACTLY sizeof(struct
  617.  * FileLock). Also, it sometimes uses uninitialized values for the lock mode...
  618.  */
  619.  
  620. Prototype struct FileLock *NewFileLock(NetFileLock *netfl, struct FileLock *fl);
  621.  
  622. struct FileLock *
  623. NewFileLock(NetFileLock *netfl, struct FileLock *fl)
  624. {
  625.     struct FileLock *newlock;
  626.     struct DeviceList *volnode = NULL;
  627.  
  628.     if (fl) {
  629.     volnode = BTOC(fl->fl_Volume);
  630.     }
  631.     if (volnode == NULL) {
  632.     volnode = VolNode;
  633.     debug(("volnode 0->%lx\n", volnode));
  634.     }
  635. #if DEBUG
  636.     if (volnode != VolNode) {
  637.     debug(("volnode != VolNode %lx != %lx\n",
  638.         volnode, VolNode));
  639.     }
  640.     if (volnode->dl_Task != DosPort) {
  641.     debug(("volnode->dl_Task != DosPort %lx != %lx\n",
  642.         volnode->dl_Task, DosPort));
  643.     }
  644. #endif
  645.  
  646.     if (newlock = dosalloc((ULONG)sizeof (*newlock))) {
  647.     newlock->fl_Key = (ULONG) netfl;
  648.     newlock->fl_Task = DosPort;
  649.     newlock->fl_Volume = (BPTR) CTOB(volnode);
  650.     Forbid();
  651.     newlock->fl_Link = volnode->dl_LockList;
  652.     volnode->dl_LockList = (BPTR) CTOB(newlock);
  653.     Permit();
  654.     } else
  655.     error = ERROR_NO_FREE_STORE;
  656.  
  657.     return newlock;
  658. }
  659.  
  660. Prototype long FreeFileLock(struct FileLock *lock);
  661.  
  662. long
  663. FreeFileLock(struct FileLock *lock)
  664. {
  665.     register struct FileLock *fl;
  666.     register struct FileLock **flp;
  667.     struct DeviceList         *volnode;
  668.  
  669.     volnode = (struct DeviceList *)BTOC(lock->fl_Volume);
  670.     flp = (struct FileLock **) &volnode->dl_LockList;
  671.     for (fl = BTOC(*flp); fl && fl != lock; fl = BTOC(fl->fl_Link))
  672.     flp = (struct FileLock **)&fl->fl_Link;
  673.  
  674.     if (fl == lock) {
  675.     *(BPTR *)flp = fl->fl_Link;
  676.     dosfree((ULONG *)fl);
  677.     OpenCount--;
  678.     return DOSTRUE;
  679.     } else {
  680.     debug(("Huh?? Could not find filelock!\n"));
  681.     return DOSFALSE;
  682.     }
  683. }
  684.  
  685. /*
  686.  * MakeFileLock allocates and initializes a new FileLock, using info
  687.  * from an existing FileLock. It always consumes the NetFileLock, even
  688.  * in case of failure.
  689.  */
  690.  
  691. Prototype BPTR MakeFileLock(NetFileLock *netfl, struct FileLock *fl, long mode);
  692.  
  693. BPTR
  694. MakeFileLock(NetFileLock *netfl, struct FileLock *fl, long mode)
  695. {
  696.     struct FileLock *newlock;
  697.  
  698.     newlock = NULL;
  699.     if (netfl) {
  700.     if (newlock = NewFileLock(netfl, fl)) {
  701.         newlock->fl_Access = mode;
  702.         OpenCount++;
  703.     } else
  704.         NetUnLock(netfl);
  705.     }
  706.  
  707.     return CTOB(newlock);
  708. }
  709.  
  710. /*
  711.  * Create Volume node and add to the device list.   This will
  712.  * cause the WORKBENCH to recognize us as a disk.   If we
  713.  * don't create a Volume node, Wb will not recognize us.
  714.  * However, we are a NET: disk, Volume node or not.
  715.  */
  716.  
  717. Prototype struct DeviceList *NewVolNode(char *name, struct DateStamp *date);
  718.  
  719. struct DeviceList     *
  720. NewVolNode(char *name, struct DateStamp *date)
  721. {
  722.     struct DeviceList *volnode;
  723.     char       *volname;        /* This is my volume name */
  724.  
  725.     if (volnode = dosalloc((ULONG)sizeof (struct DeviceList))) {
  726.     if (volname = dosalloc(33L)) {
  727.         volname[0] = strlen(name);
  728.         strcpy(volname + 1, name);      /* Make sure \0 terminated */
  729.  
  730.         volnode->dl_Type = DLT_VOLUME;
  731.         volnode->dl_Task = DosPort;
  732.         volnode->dl_DiskType = ID_DOS_DISK;
  733.         volnode->dl_Name = (BSTR)CTOB(volname);
  734.         volnode->dl_VolumeDate = *date;
  735.         volnode->dl_NetFileLockList = 0;
  736.  
  737.         if (DOSBase->dl_lib.lib_Version >= 37) {
  738.         struct DosList *dl;
  739.         debug(("LockDosList...\n"));
  740.         dl = AttemptLockDosList(LDF_VOLUMES | LDF_WRITE);
  741.         if (!((ULONG)dl & ~1)) {    /* Guru book, p. 393 */
  742.             debug(("LockDosList NOT ok\n"));
  743.             goto brute_force;
  744.         }
  745.         UnLockDosList(LDF_VOLUMES | LDF_WRITE);
  746.  
  747.         debug(("AddDosEntry...\n"));
  748.         if (AddDosEntry((struct DosList *)volnode) == DOSFALSE) {
  749.             debug(("AddDosEntry for VolNode fails!\n"));
  750.             goto error;
  751.         }
  752.         debug(("AddDosEntry: done\n"));
  753.         } else {
  754.         struct DosInfo *di;
  755.  
  756.         brute_force:
  757.         di = BTOC(((struct RootNode *) DOSBase->dl_Root)->rn_Info);
  758.  
  759.         Forbid();
  760.         volnode->dl_Next = di->di_DevInfo;
  761.         di->di_DevInfo = (long) CTOB(volnode);
  762.         Permit();
  763.         }
  764.     } else {
  765.     error:
  766.         dosfree((ULONG *)volnode);
  767.         volnode = NULL;
  768.     }
  769.     } else {
  770.     error = ERROR_NO_FREE_STORE;
  771.     }
  772.  
  773.     return volnode;
  774. }
  775.  
  776. /*
  777.  *  Give the VolNode a new name (given as a BCPL string).
  778.  */
  779.  
  780. Prototype void NewVolNodeName(char *newname);
  781.  
  782. void
  783. NewVolNodeName(char *newname)
  784. {
  785.     if (VolNode) {
  786.     register char *volname = BTOC(VolNode->dl_Name);
  787.  
  788.     memcpy(volname, newname, 1 + newname[0]);
  789.     }
  790. }
  791.  
  792. /*
  793.  * Remove Volume entry.  Since DOS uses singly linked lists, we must
  794.  * (ugg) search it manually to find the link before our Volume entry.
  795.  */
  796.  
  797. Prototype void FreeVolNode(struct DeviceList *volnode);
  798.  
  799. void
  800. FreeVolNode(struct DeviceList *volnode)
  801. {
  802.     debug(("FreeVolNode %08lx\n", volnode));
  803.  
  804.     if (volnode == NULL)
  805.     return;
  806.  
  807.     if (DOSBase->dl_lib.lib_Version >= 37) {
  808.     struct DosList *dl;
  809.  
  810.     dl = LockDosList(LDF_VOLUMES | LDF_WRITE);
  811.     (void)RemDosEntry((struct DosList *)volnode);
  812.     UnLockDosList(LDF_VOLUMES | LDF_WRITE);
  813.     } else {
  814.     struct DosInfo *di = BTOC(((struct RootNode *) DOSBase->dl_Root)->rn_Info);
  815.     register struct DeviceList *dl;
  816.     register void  *dlp;
  817.  
  818.     dlp = &di->di_DevInfo;
  819.     Forbid();
  820.     for (dl = BTOC(di->di_DevInfo); dl && dl != volnode; dl = BTOC(dl->dl_Next))
  821.         dlp = &dl->dl_Next;
  822.     if (dl == volnode) {
  823.         *(BPTR *) dlp = dl->dl_Next;
  824.     }
  825. #if DEBUG
  826.     else {
  827.         debug(("****PANIC: Unable to find volume node\n"));
  828.     }
  829. #endif                /* DEBUG */
  830.     Permit();
  831.     }
  832.  
  833.     dosfree(BTOC(volnode->dl_Name));
  834.     dosfree((ULONG *)volnode);
  835.  
  836.     if (volnode == VolNode)
  837.     VolNode = NULL;
  838. }
  839.